﻿/*********************************************************************
 * @file   FITKRecogClosedSpace.h
 * @brief  封闭空间识别算法
 * @author zhangjingxuan (hiter25@outlook.com)
 * @date   2024-10-30
 *********************************************************************/
#ifndef __FITKRECOGCLOSEDSPACE_H__
#define __FITKRECOGCLOSEDSPACE_H__
#include "FITK2DMeshToolsAPI.h"
#include "FITKAbstractRecogClosedSpace.h"
#include <OpenVolumeMesh/Geometry/VectorT.hh>
#include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>
#include <OpenVolumeMesh/Mesh/TetrahedralMeshTopologyKernel.hh>
#include <QHash>
#include <QList>

namespace Interface
{
    /**
    * @brief  封闭空间识别算法
    * @author zhangjingxuan (hiter25@outlook.com)
    * @date   2024-10-30
    */
    class FITK2DMeshToolsAPI FITKRecogClosedSpace : public FITKAbstractRecogClosedSpace
    {
    public:
        FITKRecogClosedSpace();
        ~FITKRecogClosedSpace();
        /**
        * @brief    读取数据构建网格
        * @param[i] meshPoints 点信息
        * @param[i] meshFaces  面信息
        * @return   bool ture 初始化成功,false 初始化失败
        * @author   zhangjingxuan (hiter25@outlook.com)
        * @date     2024-10-30
        */
        bool initMesh(const QList<Core::FITKNode*>& meshPoints, const QList<Interface::FITKElementTri3*>& meshFaces) override;
        /**
        * @brief    网格预处理
        * @return   QList<int> 筛选出来的单边面
        * @author   zhangjingxuan (hiter25@outlook.com)
        * @date     2024-10-30
        */
        QList<int> meshPreProcess() override;
        /**
         * @brief    封闭空间识别流程
         * @param[i] is_remove false不剔除最外层空间,true剔除最外层空间
         * @return   void
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-10-31
         */
        void recogClosedSpace(bool is_del = false) override;
        /**
        * @brief    输出封闭空间面的id
        * @return   QList<QList<int>> 封闭空间及组成封闭空间的面id
        * @author   zhangjingxuan (hiter25@outlook.com)
        * @date     2024-10-30
        */
        QList<QList<int>> getFacesIndex() override;
        /**
         * @brief    获取自由边信息
         * @return   QList<std::pair<int,int>> 存储边顶点索引的容器
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-11-01
         */
        QList<QPair<int, int>> getBoundary() override;
		/**
		 * @brief    获取封闭空间体积
		 * @return   QList<double>
		 * @author   zhangjingxuan(hiter25@outlook.com)
		 * @date     2025-01-16
		 */
		QList<double> getSpaceVolume() override;
    private:
        /**
         * @brief    封闭空间识别算法流程
         * @param[i] allclosedspace 所有封闭空间
         * @param[i] seedhf 种子半面
         * @return   void
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-18
         */
        void hfExpand(QList<QList<OpenVolumeMesh::HalfFaceHandle>>& allclosedspace, const OpenVolumeMesh::HalfFaceHandle& seedhf);
        /**
        * @brief    读取相邻半面
        * @param[i] seedhf 种子半面
        * @param[i] halfFaceLine 临时半面队列
        * @return   void
        * @author   zhangjingxuan (hiter25@outlook.com)
        * @date     2024-10-30
        */
        void readNeighborHalfFace(const OpenVolumeMesh::HalfFaceHandle& seedhf, QList<OpenVolumeMesh::HalfFaceHandle>& hfLine);
        /**
         * @brief    剔除最外层封闭空间
         * @param[i] closedspace 所有封闭空间
         * @return   void
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-18
         */
        void delExtraSpace(const QList<QList<OpenVolumeMesh::HalfFaceHandle>>& closedspace);
        /**
        * @brief    计算面夹角
        * @param[i] hev 半边向量
        * @param[i] sfn 种子面法向量
        * @param[i] afn 相邻面法向量
        * @return   double
        * @author   zhangjingxuan (hiter25@outlook.com)
        * @date     2024-10-30
        */
        double calAngle(OpenVolumeMesh::Geometry::Vec3d& hev, OpenVolumeMesh::Geometry::Vec3d& sfn, OpenVolumeMesh::Geometry::Vec3d& afn);
        /**
        * @brief    计算点到面的距离
        * @param[i] point 点
        * @param[i] halfface 半面
        * @return   double 距离
        * @author   zhangjingxuan (hiter25@outlook.com)
        * @date     2024-10-30
        */
        double calDistance(const OpenVolumeMesh::Geometry::Vec3d& point, const OpenVolumeMesh::HalfFaceHandle& halfface);
        /**
        * @brief    计算体积
        * @param[i] halfface 封闭空间半面集合
        * @return   double 体积
        * @author   zhangjingxuan (hiter25@outlook.com)
        * @date     2024-10-30
        */
        double calVolume(const QList<OpenVolumeMesh::HalfFaceHandle>& halfface);
    private:
        /**
        * @brief  OpenVolumeMesh网格对象
        * @author zhangjingxuan (hiter25@outlook.com)
        * @date   2024-10-30
        */
        OpenVolumeMesh::GeometricPolyhedralMeshV3d* m_mesh{ nullptr };
        /**
        * @brief  所有半面的哈希表
        * @author zhangjingxuan (hiter25@outlook.com)
        * @date   2024-10-30
        */
        QHash<int, OpenVolumeMesh::HalfFaceHandle> m_allHalfFaces{};
        /**
        * @brief  组成封闭空间的半面
        * @author zhangjingxuan (hiter25@outlook.com)
        * @date   2024-10-30
        */
        QHash<int, QList<OpenVolumeMesh::HalfFaceHandle>> m_allClosedSpaceHalfFaces{};
		/**
		 * @brief  每个封闭空间体积
		 * @author zhangjingxuan(hiter25@outlook.com)
		 * @date   2025-01-16
		 */
		QList<double> m_spaceVolume;
    };
}
#endif // !__FITKRECOGCLOSEDSPACE_H__